#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "crc32.h"
#ifndef uint
#define uint unsigned int
#endif
#define byte char
#define TD_VERSION "0.3"

enum {INVALID_SESSION = 2, ALREADY_EXIST, INVALID_ROW, INVALID_SUBBASE, INVALID_BASE, INVALID_MODE, INVALID_CASE};
enum {ROW_NOT_EXIST = 8, SUBBASE_NOT_EXIST, BASE_NOT_EXIST, INVALID_STRING, CANT_WRITE};

enum {SELECTED = 2, GET, SELECT, NO_SELECT, O_AUTO, O_MANUAL, O_VIRTUAL, CASE_SENS, NO_CASE_SENS};

typedef struct _row row;
struct _row
{
  uint hash;
  char *ident;
  char *val;
  row *next;
  row *prev;
};

typedef struct _subbase subbase;
struct _subbase
{
	uint hash; 
	char *ident;
	subbase *parent;
	subbase *enfant;
	subbase *der_enfant;
	row *rows;
	row *last_row;
	subbase *next;
	subbase *prev;
};

typedef struct _racine racine;
struct _racine
{
  subbase *base;
  byte case_flag;
  byte mode;
  racine *next;
  racine *prev;
};

typedef struct _session session;
struct _session
{
  subbase *subptr;
  row *rowptr;
  subbase *baseptr;
  racine *rootptr;
};

typedef struct _td_row td_row;
struct _td_row
{
  char *ident;
  char *val;
  byte issub;
};

extern racine *root_head;
extern session **sess_tab;
extern uint sess_top;
extern char *bdd_path;
extern uint td_err;
extern char *tdversion;

subbase *add_subbase (subbase * par, subbase * head, char *id, byte c_s);
racine *add_base (racine * head, char *id, byte c_s);
row *add_row (subbase *parent, char *id, char *va, byte c_s);
uint add_session (void);

subbase *del_subbase (subbase * head, subbase * one);
row *del_row (subbase *parent, row * des);
racine *del_base (racine * head, racine * one);

row *get_row (row * head, char *se, byte c_s);
session *get_session (unsigned int si);
subbase *get_subbase (subbase * head, char *se, byte c_s);
racine *get_base (racine * head, char *se);
racine *get_racine_by_base (racine * head, subbase * ptr);

void update_ident_subbase (subbase * s, char *nid);
void update_val_row (row * r, char *nval);
void update_ident_row (row * r, char *nid);

td_row *make_row_td_row (row * r);
td_row *make_subbase_td_row (subbase * r);

void free_session (uint si);

byte valid_string (char *str);
byte valid_basename (char *str);
void clean_session_base (subbase * p);
void clean_session_subbase (subbase * p);
void clean_session_row (row * p);
byte session_on_base (subbase * p, uint s);
void low_string (char *str);
char *dup_low_string (char *str);
char **str_to_tab (char *buffer, char delim, int *nb);


unsigned int td_open_base (char *se, byte c_s, byte mode);
byte td_close_base (uint si);
byte td_close_session (uint si);
unsigned int td_new_session (unsigned int si);
char *td_error (uint nid, char *lang);

unsigned int td_select_base (char *se);
td_row *td_select_row (unsigned int si, char *se);
td_row *td_select_subbase (unsigned int si, char *se);
td_row *td_select_row_p (unsigned int si, char *buffer, char delim);
td_row *td_select_row_r (unsigned int si, int *nerr, char *srow, ...);
td_row *td_select_subbase_p (unsigned int si, char *buffer, char delim);
td_row *td_select_subbase_r (unsigned int si, int *nerr, ...);
td_row *td_select_next_row (unsigned int si);
td_row *td_select_next_subbase (unsigned int si);
td_row *td_select_first_subbase (unsigned int si);
td_row *td_select_first_row (unsigned int si);
td_row *td_select_parent_subbase (unsigned int si);

byte td_add_row (unsigned int si, char *id, char *va, byte mode);
byte td_add_subbase (unsigned int si, char *id, byte mode);
uint td_add_base (char *se, byte c_s, byte o_mode);

byte td_del_subbase (unsigned int si, char *id, byte mode);
byte td_del_row (unsigned int si, char *id, byte mode);
byte td_del_base (unsigned int si, char *id, byte mode);

byte td_update_val_row_p (unsigned int si, char *se, char delim, char *nval);
byte td_update_val_row (unsigned int si, char *se, char *nval, byte mode);
byte td_update_ident_row_p (unsigned int si, char *se, char delim, char *nid);
byte td_update_ident_row (unsigned int si, char *se, char *nid, byte mode);
byte td_update_ident_subbase (unsigned int si, char *nid);

void td_free_row (td_row *k);
int td_init (char *path);
void td_clean (void);
byte td_write_base (uint si);
byte td_print_base (unsigned int si);

void pouf (subbase * b);
byte write_bdd (subbase *b);
byte read_bdd (char *bname, byte mode, byte c_s);
